package org.example.utils;

import org.apache.commons.io.IOUtils;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.security.SecureRandom;


/**
*@Description   AES加密解密工具包
*@Author  24025
*@Date  2022/2/18
*/
public class AESUtils {

    // 加密算法
    private static final String ALGORITHM = "AES";
    private static final int KEY_SIZE = 128;

    /**
     * 生成随机密钥
     */
    public static String getSecretKey() throws Exception {
        return getSecretKey(null);
    }
    /**
     * 根据密钥种子生成密钥
     */
    private static String getSecretKey(String seed) throws Exception {

        // 生成 asc 密钥
        KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
        SecureRandom secureRandom;
        if (seed != null && !"".equals(seed)) {
            secureRandom = new SecureRandom(seed.getBytes());
        } else {
            secureRandom = new SecureRandom();
        }
        keyGenerator.init(KEY_SIZE, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        return Base64Utils.encode(secretKey.getEncoded());
    }
    /**
     * AES文件流加密
     */
    public static void encryptFile(String key, InputStream fileInputStream, String filePath) throws Exception {

        Key k = toKey(Base64Utils.decode(key));
        byte[] raw = k.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        // 文件流加密
        CipherInputStream cin = new CipherInputStream(fileInputStream, cipher);

        BufferedInputStream in = null;
        BufferedOutputStream out = null;

        in = new BufferedInputStream(cin);
        out = new BufferedOutputStream(new FileOutputStream(filePath));
        IOUtils.copy(in, out);

        cin.close();
        in.close();
        out.close();
    }
    /**
     * 转换密钥
     */
    private static Key toKey(byte[] key) {
        SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
        return secretKey;
    }
}
